package doc;


import cn.demoncat.util.lang.entity.Result;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.annotation.Version;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.CompoundIndexes;
import org.springframework.data.mongodb.core.index.IndexDirection;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

import java.time.LocalDate;
import java.time.LocalDateTime;

// MongoDB的Collection映射类：如果检查到POJO对应的集合不存在，就会根据POJO类的声明及注解来创建
@Document(
	// 集合名称，默认"类名驼峰"
 	collection = "user"
)
//复合索引集
@CompoundIndexes({
	//复合索引（1个POJO类只能有1个，多个使用@CompoundIndexes集成）
	@CompoundIndex(
		//定义复合索引(name域升序，age域逆序)
		def="{name:1,age:-1}",
		//是否唯一(有重复值时抛异常)
		unique=true, 
		//后台创建索引(与插入操作异步)
		background=true
	)
})
//复合索引（1个POJO类只能有1个，多个使用@CompoundIndexes集成）
@CompoundIndex(
	// 索引名称
	name="localtion_name_idx", 
	// 地理空间索引：用$geoNear查询的集合，必须（只）有1个"2d"（平面）或"2dsphere"（球面）的索引（用于location字段，建议联合其它查询条件）
	def = "{location:'2dsphere', type:1, name:1}", 
	//是否唯一(有重复值时抛异常)
	unique=true,
	//后台创建索引(与插入操作异步)
	background = true
)
@Data
public class User{

	// 文档的主键，对应Docuemnt._id字段
	// 默认会将id属性映射为@Id
	// String类型的id，未赋值时自动分配ObjectId值，可以进行类型转换
    @Id
    private String id;
    
    // 指定域名：默认为属性名
 	@Field(value="myname")
    private String name;
 	
 	// 单域索引
 	@Indexed(
 		// 升序/逆序
 		direction=IndexDirection.ASCENDING, 
 		// 是否唯一(有重复值时抛异常)
 		unique=true, 
 		// 索引名(集合名.索引名，默认自动生成)
 		name="indexName", 
 		// 后台创建索引(与插入操作异步)
 		background=true
	)
 	private String type;
 	
 	// 时间字段：建议使用long存储，规避类型转换和时区问题
 	private Long updateTime;
 	
 	// 时间字段：MongoDB会以UTC时间存储为ISODate，查询时自动进行转换
 	private LocalDateTime time;
 	// 日间字段：MongoDB会以UTC时间存储为ISODate，查询时自动进行转换
	private LocalDate date;
 	
 	// 声明不存储/映射的属性
    @Transient 
    private long count;

    // 乐观锁字段
    // 查询数据 > 修改属性 > 更新 > （MongoDB）对比version，未变更则更新并递增，已变更则抛出OptimisticLockingFailureException
    @Version 
    private Long version;
    
	// 地理空间字段（需要定义唯一的地理空间索引）
	// 定位点：[x, y]
	private double[] location;
	
	// 周边距离字段（返回near查询结果，不映射）
	@Transient
	private double dis;
	
	 //声明引用其它文档(根据引用类的注解，查询对应的集合)：指定引用文档所在的库(默认为本库)，指定懒查询
	@DBRef(db="test2",lazy=true )
	private Result result;

}
